#include "crvm.h"
#include <stdio.h>


static char *opbuf;

void prinf_opcode(romaddr opcode,char * str)
{
	sprintf(opbuf,"%04X %-6s",opcode,str);
}

void prinf_opcode_byte(romaddr opcode,char * str,word val)
{
	sprintf(opbuf,"%04X %-6s%#X",opcode,str,val);
}

void prinf_opcode_byte_bit(romaddr opcode,char * str,byte reg,byte bit)
{
	sprintf(opbuf,"%04X %-6sR(%X),B(%x)",opcode,str,reg,bit);
}

void prinf_opcode_byte_RA(romaddr opcode,char * str,byte reg)
{
	sprintf(opbuf,"%04X %-6sR(%X),",opcode,str,reg);
	if(opcode &(1<<7))
			strcat(opbuf,"R");
	else
			strcat(opbuf,"A");
}

void prinf_opcode_byte_RA_3(romaddr opcode,char * str,byte reg)
{
	sprintf(opbuf,"%04X %-6sR(%X),",opcode,str,reg);
	if(opcode &(1<<3))
			strcat(opbuf,"R");
	else
			strcat(opbuf,"A");
}

char* disassemble_inst(word opcode,char *buffer)
{
	word decode;
	opcode &= 0x3FFF;
	opbuf = buffer;
	if(opcode == 0 )
		prinf_opcode(opcode,"NOP");
	else if(opcode == 2 )
		prinf_opcode(opcode,"SLEEP");
	else if(opcode == 3 )
		prinf_opcode(opcode,"CLRWT");
	else if(opcode == 4 )
		prinf_opcode(opcode,"RETI");
	else if(opcode == 5 )
		prinf_opcode(opcode,"RET");
	else if(opcode == 6 )
		prinf_opcode(opcode,"CLRIF");
	else if(opcode == 7 )
		prinf_opcode(opcode,"STDBY");
	else if(opcode == 8 )
		prinf_opcode(opcode,"CLRA");

	decode =  (opcode & 0x3F00)>>8;
	if(decode == 0x38)
		prinf_opcode_byte(opcode,"LDIA",opcode & 0xff);
	else if(decode == 0x39)
		prinf_opcode_byte(opcode,"CMPIA",opcode & 0xff);
	else if(decode == 0x3a)
		prinf_opcode_byte(opcode,"IORIA",opcode & 0xff);
	else if(decode == 0x3b)
		prinf_opcode_byte(opcode,"XORIA",opcode & 0xff);
	else if(decode == 0x3c)
		prinf_opcode_byte(opcode,"RTIA",opcode & 0xff);
	else if(decode == 0x3d)
		prinf_opcode_byte(opcode,"ADCIA",opcode & 0xff);
	else if(decode == 0x3e)
		prinf_opcode_byte(opcode,"SBCIA",opcode & 0xff);
	else if(decode == 0x3f)
		prinf_opcode_byte(opcode,"ANDIA",opcode & 0xff);

	decode =  opcode & 0x3c00;
	switch(decode>>10)
	{
	case 0x02:
		prinf_opcode_byte_bit(opcode,"BCR",opcode & 0x7f,(opcode >> 7) & 0x07);
			break;

	case 0x03:
		prinf_opcode_byte_bit(opcode,"BTRSC",opcode & 0x7f,(opcode >> 7) & 0x07);
			break;

	case 0x06:
		prinf_opcode_byte_bit(opcode,"BSR",opcode & 0x7f,(opcode >> 7) & 0x07);
			break;

	case 0x07:
		prinf_opcode_byte_bit(opcode,"BTRSS",opcode & 0x7f,(opcode >> 7) & 0x07);
			break;
	case 0x08:
	case 0x09:
		prinf_opcode_byte(opcode,"JUMP",opcode & 0x7ff);
		break;
	case 0x0a:
	case 0x0b:
		prinf_opcode_byte(opcode,"CALL",opcode & 0x7ff);
		break;
	default:
		break;
	}	
	decode =  opcode & 0x3f80;
	switch(decode>>7)
	{
	case 1:
		prinf_opcode_byte_RA(opcode,"STAR",opcode & 0x7f);
		break;

	case 2:
		prinf_opcode_byte_RA_3(opcode,"CTRLR",opcode & 0x7);
		break;
	case 3:
		prinf_opcode_byte(opcode,"CLRR",opcode & 0x7f);
		break;
	case 4:
	case 5:
		prinf_opcode_byte_RA(opcode,"IORAR",opcode & 0x7f);
		break;
	case 6:
	case 7:
		prinf_opcode_byte_RA(opcode,"XORAR",opcode & 0x7f);
		break;

	case 8:
	case 9:
		prinf_opcode_byte_RA(opcode,"ANDAR",opcode & 0x7f);
		break;
	case 0x0a:
	case 0x0b:
		prinf_opcode_byte_RA(opcode,"ADDAR",opcode & 0x7f);
		break;
	case 0xc:
	case 0x0d:
		prinf_opcode_byte_RA(opcode,"SUBAR",opcode & 0x7f);
		break;
	case 0x0e:
	case 0x0f:
		prinf_opcode_byte_RA(opcode,"LDR",opcode & 0x7f);
		break;
	case 0x20:
	case 0x21:
		prinf_opcode_byte_RA(opcode,"COMR",opcode & 0x7f);
		break;
	case 0x22:
	case 0x23:
		prinf_opcode_byte_RA(opcode,"DECR",opcode & 0x7f);
		break;
	case 0x24:
	case 0x25:
		prinf_opcode_byte_RA(opcode,"DRSZ",opcode & 0x7f);
		break;
	case 0x26:
	case 0x27:
		prinf_opcode_byte_RA(opcode,"INCR",opcode & 0x7f);
		break;
	case 0x28:
	case 0x29:
		prinf_opcode_byte_RA(opcode,"IRSZ",opcode & 0x7f);
		break;

	case 0x2a:
	case 0x2b:
		prinf_opcode_byte_RA(opcode,"SWAPR",opcode & 0x7f);
		break;

	case 0x2c:
	case 0x2d:
		prinf_opcode_byte_RA(opcode,"RLR",opcode & 0x7f);
		break;

	case 0x2e:
	case 0x2f:
		prinf_opcode_byte_RA(opcode,"RRR",opcode & 0x7f);
		break;

	case 0x60:
	case 0x61:
		prinf_opcode_byte_RA(opcode,"ADCAR",opcode & 0x7f);
		break;

	case 0x62:
	case 0x63:
		prinf_opcode_byte_RA(opcode,"SBCAR",opcode & 0x7f);
		break;

	case 0x64:
	case 0x65:
		prinf_opcode_byte_RA(opcode,"SRR",opcode & 0x7f);
		break;

	case 0x66:
	case 0x67:
		prinf_opcode_byte_RA(opcode,"SLR",opcode & 0x7f);
		break;

	case 0x68:
	case 0x69:
		prinf_opcode_byte_RA(opcode,"DAR",opcode & 0x7f);
		break;

	case 0x6a:
		prinf_opcode_byte(opcode,"XCHAR",opcode & 0x7f);
		break;

	case 0x6b:
		prinf_opcode_byte_RA(opcode,"CMPAR",opcode & 0x7f);
		break;

	case 0x6c:
	case 0x6d:
		prinf_opcode_byte_bit(opcode,"BCTR",opcode & 0x7f,(opcode >> 7) & 0x07);
		break;

	case 0x6e:
	case 0x6f:
		prinf_opcode_byte_bit(opcode,"BRTC",opcode & 0x7f,(opcode >> 7) & 0x07);
		break;
	default:		
		break;
	}
	return opbuf;
}


